#include <openvino/openvino.hpp>

#include <opencv2/dnn.hpp>
#include "opencv2/opencv.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"

#include <sys/prctl.h>

#include <cstdlib>
#include <fstream>
#include <iostream>
#include <sstream>
#include <ctime>
#include <dirent.h>

#include <iterator>
#include <memory>
#include <sstream>
#include <string>
#include <vector>

#include <unistd.h>
#include <sys/time.h>

#include "yolo.h"
#include "PaddleOcrOpenvino.h"

PaddleOcrOpenvino paddleOcr;
Yolo yolo;
Yolo yolo1;

unsigned long long getTimeStamps(void)
{
    struct timeval tv;
    unsigned long long timeStamps = 0;

    gettimeofday(&tv, NULL);
    timeStamps = tv.tv_sec * 1000 + tv.tv_usec / 1000.0;

    return timeStamps;
}

void traverse_dir(const char *dir_path)
{
    char path[1024];

    DIR *dir = opendir(dir_path);
    if (dir == NULL)
        return;

    struct dirent *dp;
    while ((dp = readdir(dir)) != NULL)
    {
        unsigned long long t0, t1, t2, t3, t4, t5;

        if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
            continue;

        sprintf(path, "%s/%s", dir_path, dp->d_name);

        if (dp->d_type == DT_DIR)
        {
            int tmp = atoi(dp->d_name);

            traverse_dir(path);
        }
        else if (dp->d_type == DT_REG)
        {
            //if (strstr(dp->d_name, ".jpg") && strstr(dp->d_name, "back"))
            if (strstr(dp->d_name, ".jpg"))
            {
                // printf("id = %d\r\n", nowid);
                // printf("%s\n", path);
                int trueCount = 0;
                int bufid[8];
                memset(bufid, 0, sizeof(int) * 8);


                std::string img_path = path;

                std::vector<YoloBox> yoloBoxes;
                cv::Mat img = cv::imread(img_path);
                if(img.empty())
                {
                    continue;
                }
                printf("%s\r\n", img_path.c_str());
                if (img.empty() && strstr(img_path.c_str(), "plate"))
                {
                    continue;
                }

                cv::Mat processImg = img.clone();
                cv::Mat yoloImg = img.clone();

                t0 = getTimeStamps();
                yoloBoxes = yolo.Detect(yoloImg);
                t1 = getTimeStamps();

                for (int i = 0; i < yoloBoxes.size(); i++)
                {
                    if(yoloBoxes[i].x < 0)
                    {
                        yoloBoxes[i].x = 0;
                    }
                    if(yoloBoxes[i].y < 0)
                    {
                        yoloBoxes[i].y = 0;
                    }
                    if(yoloBoxes[i].x + yoloBoxes[i].w >= img.cols)
                    {
                        yoloBoxes[i].w = yoloBoxes[i].x - img.cols - 1;
                    }
                    if(yoloBoxes[i].y + yoloBoxes[i].h >= img.rows)
                    {
                        yoloBoxes[i].h = yoloBoxes[i].y - img.rows - 1;
                    }

                    cv::Rect rect(yoloBoxes[i].x, yoloBoxes[i].y, yoloBoxes[i].w, yoloBoxes[i].h);
                    
                    switch (yoloBoxes[i].id)
                    {
                    case 0: // car blue
                        cv::rectangle(img, rect, cv::Scalar(255, 0, 0), 2, 1, 0);
                        break;
                    case 1: // 3 green
                        cv::rectangle(img, rect, cv::Scalar(0, 255, 0), 2, 1, 0);
                        break;
                    case 2: // 2  red
                        cv::rectangle(img, rect, cv::Scalar(0, 0, 255), 2, 1, 0);
                        break;
                    case 3: // truck yellow
                        cv::rectangle(img, rect, cv::Scalar(0, 128, 255), 2, 1, 0);
                        break;
                    case 4: // other white
                        cv::rectangle(img, rect, cv::Scalar(255, 255, 255), 2, 1, 0);
                        break;
                    default:
                        cv::rectangle(img, rect, cv::Scalar(255, 128, 255), 2, 1, 0);
                    }

                    int score, lastScore;
                    std::string retStr, retStr1, retStr0, retStrOri;

                    paddleOcr.Ocr(processImg, rect, retStrOri, score, lastScore);
                    printf("original retStr = %s, score = %d, lastScore = %d\r\n",
                            retStrOri.c_str(), score, lastScore);

                    t2 = getTimeStamps();
                    paddleOcr.Ocr2rd(processImg, rect, retStr, score, lastScore);
                    t3 = getTimeStamps();
                    printf("retStr = %s, score = %d, lastScore = %d\r\n", retStr.c_str(), score, lastScore);
                    

                    cv::Mat retImg;
                    t4 = getTimeStamps();
                    paddleOcr.OcrEDLine(processImg, retImg, rect, retStr1, score, lastScore);
                    t5 = getTimeStamps();
                    printf("retStr = %s, score = %d, lastScore = %d\r\n", retStr1.c_str(), score, lastScore);

                    cv::Mat processImg1;
                    cv::normalize(retImg, processImg1, 25, 255, cv::NORM_MINMAX);
                    if(processImg1.rows > 0)
                    {
                        paddleOcr.Ocr(processImg1, retStr0, score);
                        printf("retStr = %s, score = %d, lastScore = %d\r\n", retStr0.c_str(), score);
                        imshow("gray", processImg1);
                    }
                    
                }

                t0 = getTimeStamps();
                yoloBoxes = yolo1.Detect(yoloImg);
                t1 = getTimeStamps();

                for (int i = 0; i < yoloBoxes.size(); i++)
                {
                    if(yoloBoxes[i].x < 0)
                    {
                        yoloBoxes[i].x = 0;
                    }
                    if(yoloBoxes[i].y < 0)
                    {
                        yoloBoxes[i].y = 0;
                    }
                    if(yoloBoxes[i].x + yoloBoxes[i].w >= img.cols)
                    {
                        yoloBoxes[i].w = yoloBoxes[i].x - img.cols - 1;
                    }
                    if(yoloBoxes[i].y + yoloBoxes[i].h >= img.rows)
                    {
                        yoloBoxes[i].h = yoloBoxes[i].y - img.rows - 1;
                    }

                    cv::Rect rect(yoloBoxes[i].x, yoloBoxes[i].y, yoloBoxes[i].w, yoloBoxes[i].h);
                    
                    switch (yoloBoxes[i].id)
                    {
                    case 0: // car blue
                        cv::rectangle(img, rect, cv::Scalar(255, 255, 0), 2, 1, 0);
                        break;
                    case 1: // 3 green
                        cv::rectangle(img, rect, cv::Scalar(0, 255, 0), 2, 1, 0);
                        break;
                    case 2: // 2  red
                        cv::rectangle(img, rect, cv::Scalar(0, 0, 255), 2, 1, 0);
                        break;
                    case 3: // truck yellow
                        cv::rectangle(img, rect, cv::Scalar(0, 128, 255), 2, 1, 0);
                        break;
                    case 4: // other white
                        cv::rectangle(img, rect, cv::Scalar(255, 255, 255), 2, 1, 0);
                        break;
                    default:
                        cv::rectangle(img, rect, cv::Scalar(255, 128, 255), 2, 1, 0);
                    }

                    int score, lastScore;
                    std::string retStr, retStr1, retStr0, retStrOri;

                    paddleOcr.Ocr(processImg, rect, retStrOri, score, lastScore);
                    printf("1 original retStr = %s, score = %d, lastScore = %d\r\n",
                            retStrOri.c_str(), score, lastScore);

                    t2 = getTimeStamps();
                    paddleOcr.Ocr2rd(processImg, rect, retStr, score, lastScore);
                    t3 = getTimeStamps();
                    printf("1 retStr = %s, score = %d, lastScore = %d\r\n", retStr.c_str(), score, lastScore);
                    

                    cv::Mat retImg;
                    t4 = getTimeStamps();
                    paddleOcr.OcrEDLine(processImg, retImg, rect, retStr1, score, lastScore);
                    t5 = getTimeStamps();
                    printf("1 retStr = %s, score = %d, lastScore = %d\r\n", retStr1.c_str(), score, lastScore);

                    cv::Mat processImg1;
                    cv::normalize(retImg, processImg1, 100, 180, cv::NORM_MINMAX);
                    cv::normalize(processImg1, processImg1, 0, 255, cv::NORM_MINMAX);
                    if(processImg1.rows > 0)
                    {
                        paddleOcr.Ocr(processImg1, retStr0, score);
                        printf("1 retStr = %s, score = %d, lastScore = %d\r\n", retStr0.c_str(), score);
                        imshow("gray", processImg1);
                    }
                    
                }                

                // printf("%d ms\r\n",
                //         (((t1.tv_sec - t0.tv_sec) * 1000 + (t1.tv_usec - t0.tv_usec) / 1000)));
                sleep(1);

                cv::imshow("img", img);
                cv::waitKey(0);
            }
        }
    }

    closedir(dir);
}

int main(void)
{
    cv::namedWindow("img", 0);
    cv::resizeWindow("img", 512 * 1.8, 288 * 1.8);

    yolo.Init("/mnt/hgfs/cars/data_image_src/train/xiefei/foshan/parkid/cmp/best.xml");

    yolo1.Init("/mnt/hgfs/cars/data_image_src/train/xiefei/foshan/parkid/cmp/best.xml");

    paddleOcr.Init("/mnt/hgfs/cars/mycode/PaddleOCR-release-2.6/output/ch_PP-OCRv4_rec_infer/ppocr.xml", 
            "/mnt/hgfs/cars/mycode/PaddleOCR-release-2.6/output/ch_PP-OCRv4_rec_infer/ppocr_keys_v1.txt");

    traverse_dir("/mnt/hgfs/cars/data_image_src/train/xiefei/foshan/parkid/cmpimg");

    // yolo.Init("/home/ubuntu/lingcong/testWeight/yoloparkid/best.xml");

    // paddleOcr.Init("/home/ubuntu/lingcong/testWeight/paddleocr/ppocr.xml", 
    //         "/home/ubuntu/lingcong/testWeight/paddleocr/ppocr_keys_v1.txt");

    // traverse_dir("/home/ubuntu/lingcong/testImg");
    
    return 0;
}
